package com.example.demo.heima.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;

/**
 * ******************************************************
 *
 * @author liugh9
 * @version 1.0
 * @classname NioServer
 * @description
 * @date 2023/07/16 10:53
 * <p>
 * ******************************************************
 */
public class NioServer {

    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false); // 配置非阻塞
        // 开启端口监听
        serverSocketChannel.socket().bind(new InetSocketAddress(8888));

        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        new Thread(new SingleReactor(selector)).start();

    }


    static class SingleReactor implements Runnable {

        private final Selector selector;

        public SingleReactor(Selector selector) {
            this.selector = selector;
        }

        @Override
        public void run() {
            // 开启多路服用检测
            while (true) {
                try {
                    final int select = selector.select(); // 有多少个需要处理的key
                    final Set<SelectionKey> selectionKeys = selector.selectedKeys(); // 需处理的key集合
                    final Iterator<SelectionKey> iterator = selectionKeys.iterator();
                    while (iterator.hasNext()) {
                        final SelectionKey selectionKey = iterator.next();
                        dealSelectionKey(selectionKey);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private void dealSelectionKey(SelectionKey selectionKey) throws IOException {
            if (selectionKey.isValid()) {
                // 按照事件类型处理
                if (selectionKey.isAcceptable()) {
                    final ServerSocketChannel serverSocketChannel = (ServerSocketChannel)selectionKey.channel();
                    final SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                }

                if (selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    final ByteBuffer buffer = ByteBuffer.allocate(1024);
                    socketChannel.read(buffer); // 当前是将channel的数据写到buffer

                    // 从buff中拿数据
                    buffer.flip(); // 切换读操作
                    byte[] bytes = new byte[buffer.remaining()];
                    buffer.get(bytes); // 该操作是需要读buffer中的数据到bytes
                    final String msg = new String(bytes, Charset.defaultCharset());
                    System.out.println("从客户端读到数据："+msg);

                    // bus


                    // 向buff中写数据
                    ByteBuffer buffer1 = ByteBuffer.allocate(1024);
                    buffer1.put("hello nioclient, i am nioserver".getBytes(StandardCharsets.UTF_8)); // 当前是写buffer
                    buffer1.flip(); // 切换读操作
                    socketChannel.write(buffer1); // 该操作是需要读buffer
                    // 二选一
                    // 向buff中写数据
                    /*buffer.clear();
                    buffer.put("hello nioclient, i am nioserver".getBytes(StandardCharsets.UTF_8)); // 当前是写buffer
                    buffer.flip(); // 切换读操作
                    socketChannel.write(buffer); // 该操作是需要读buffer*/
                }
            }

        }
    }
}
